cuda.core: add executable graph node updates - #2473
Conversation
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
|
/ok to test |
Install a private CUDA user object per graph executable so later node updates can retain replacement resources safely.
Expose ephemeral graph-node views that update complete executable parameters while retaining every replacement resource CUDA may still use.
Exercise public mutators, rollback, source reclamation, independent ownership, whole updates, and in-flight cleanup end to end.
450d1d5 to
dd97efa
Compare
|
/ok to test |
Instantiation and whole-graph update each went through a prepare/commit pair. That exposed an opaque transaction type over the internal C++ interface and split the exec ownership contract between C++ and Cython, unlike every other resource handle, which a single create_* function owns end to end. Replace the pairs with create_graph_exec_handle and graph_exec_update. Each stages a fresh attachment accumulator on the source graph, makes the CUDA call with the GIL released, and adopts or publishes the result, so the staging transaction becomes a stack guard in the anonymous namespace instead of a header type. Cython keeps only what belongs to it: filling the instantiation params and decoding the failure reasons. The two driver entry points move into the C++ loader table with the calls. Convert the attachment append transaction to the unique_ptr plus rollback deleter pattern that node attachments already use, which retires the committed flag in favor of the same release-and-delete mechanism. Drop GraphExecBox::attachment_object, which nothing reads.
Three gaps remained around owners attached to an executable graph. Sequential updates to the same node must keep the superseded owner reachable, because CUDA cannot detach user objects from an executable; verified by breaking the append into a replace, which fails the new test on exactly that assertion. Closing an executable while a launch is in flight must not retire the accumulator, since the launch still writes through the buffer that an individual node update attached. A child-graph update attaches no owner of its own and relies on CUDA cloning the replacement graph's user object references into the executable. Assert that contract directly: the callback outlives the definition that supplied it and is released with the executable.
CUDA accepts user objects on a CUgraph only, so an executable graph can never receive an owner after it exists. Document the consequence: one accumulator is retained on the source graph, propagated by instantiation or whole-graph update, and then released from the source so the executable becomes its only owner. Record why an owner is never removed once appended, and correct the two Scope entries that still described executable graphs as untracked. State the retention limit in the release notes as well. The API reference already documents it, but the note is what a reader sees when adopting the feature, and retention that looks unbounded deserves the warning there.
|
/ok to test |
|
Describe retention and complete-replacement rules without framing the notes around CUDA limitations, and shorten the executable attachment design section to problem, solution, and append-vs-replace limits.
Describe how callers use the view rather than how the binding retains handles or when CUDA validates the node association.
|
/ok to test |
| synchronization as the underlying CUDA graph. | ||
| 11. An accumulator is retained on the source graph before the CUDA call that | ||
| propagates it into an executable graph. | ||
| 12. The source graph's temporary reference is released on every path, which |
There was a problem hiding this comment.
I don't understand "on every path" in this sentence.
There was a problem hiding this comment.
This whole section grew out of control. I cut it back to just cover key invariants covering the whole topic.
There was a problem hiding this comment.
I don't understand what the two owners are in the list that follows this stence.
There was a problem hiding this comment.
Hard to understand. Consider rewriting the sentence
If scheduling fails, attachments stay queued and a later enqueue or safe cuda.core entry retries.
| raise TypeError( | ||
| f"expected GraphBuilder or GraphDefinition, got {type(source).__name__}") | ||
|
|
||
| params.flags = 0 |
There was a problem hiding this comment.
Nit: declare and initialize params here?
| else: | ||
| view.update(replacement) | ||
| elif isinstance(case.node, MemsetNode): | ||
| view.update( |
There was a problem hiding this comment.
Would
view.update(**replacement)
work here?
There was a problem hiding this comment.
Actually, the replacement dict has extra keys in some cases, so it doesn't work here.
Clarify attachment ownership and deferred-cleanup docs, trim the invariants list to the cross-cutting rules, initialize instantiate params with Cython struct syntax, and simplify the executable update test helper.
The shared replacement fixture carries extra fields that are not update parameters, so spreading it as kwargs breaks memset and kernel cases.
Summary
graph[node]views for complete kernel, memcpy, memset, host-callback, child-graph, and event updates, plus executable enable state where CUDA supports it.Changes
cuGraphExecNodeSetParamswhile CUDA remains authoritative for node association.Related Work
Closes #2353.
Closes #2354.